﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading.Tasks;
using MDT.LifeSewagePlatform.Conmmon;
using MDT.LifeSewagePlatform.Entity;
using MDT.LifeSewagePlatform.IRepository;
using Microsoft.EntityFrameworkCore;

namespace MDT.LifeSewagePlatform.Repository
{
    public class DrugDetailRepository : BaseRepository<DrugDetailEntity>, IDrugDetailRepository
    {
        [Autowired]
        private SystemConfigEntity systemConfig { get; set; }
        public IQueryable<DrugDetailUnion> GetDrugDetails(Expression<Func<DrugDetailUnion, bool>> expression)
        {
            var query = from drugdetail in _dbContext.DrugDetail.AsNoTracking()
                        join file in _dbContext.Files.AsNoTracking() on drugdetail.FileID equals file.ID
                        join area in _dbContext.Regions.AsNoTracking() on drugdetail.AreaID equals area.ID into LeftArea
                        from leftarea in LeftArea.DefaultIfEmpty()
                        join city in _dbContext.Regions.AsNoTracking() on file.CityID equals city.ID
                        join place in _dbContext.Details.AsNoTracking() on drugdetail.PlaceTypeID equals place.ID
                        select new DrugDetailUnion
                        {
                            CityID = file.CityID,
                            AreaID =drugdetail.AreaID,
                            Quarter = drugdetail.Quarter,
                            Diamorphine = drugdetail.Diamorphine,
                            Methylamphetamine = drugdetail.Methylamphetamine,
                            Ketamine = drugdetail.Ketamine,
                            Cyclohexanone = drugdetail.Cyclohexanone,
                            Cocaine = drugdetail.Cocaine,
                            Ecstasy = drugdetail.Ecstasy,
                            ReducedTotal = drugdetail.ReducedTotal,
                            MonitoringSite = drugdetail.MonitoringSite,
                            CompanyID = file.CompanyID,
                            PlaceTypeID = drugdetail.PlaceTypeID,
                            PlaceTypeName =place.RowName,
                            MonitorTime = drugdetail.MonitorTime,
                            AreaName =leftarea==null ? "无": leftarea.DisplayName,
                            CityName = city.DisplayName
                        };
            return query.Where(expression);
        }

        public async Task<DrugDetailEntity> GroupByAverage(IQueryable<DrugDetailUnion> drugDetailUnion)
        {
            return await drugDetailUnion.
                GroupBy(d => new { })
                .Select(d => new DrugDetailEntity
                {
                    Cyclohexanone = d.Average(x => x.Cyclohexanone),
                    Diamorphine = d.Average(x => x.Diamorphine),
                    Methylamphetamine = d.Average(x => x.Methylamphetamine),
                    Ketamine = d.Average(x => x.Ketamine),
                    Ecstasy = d.Average(x => x.Ecstasy),
                    Cocaine = d.Average(x => x.Cocaine),
                }).FirstOrDefaultAsync();
        }

        public async Task<Dictionary<string, double>> GroupByPlaceAverage(IQueryable<DrugDetailUnion> drugDetailUnion)
        {
            return await drugDetailUnion.GroupBy(d => d.MonitoringSite).
                Select(d => new DrugDetailEntity
                {
                    MonitoringSite = d.Key,
                    ReducedTotal = d.Average(t => t.ReducedTotal),
                }).ToDictionaryAsync(d => d.MonitoringSite, d => d.ReducedTotal);
        }

        public async Task<Dictionary<int, double>> GroupByAverage(IQueryable<DrugDetailUnion> drugDetailUnion, eGroupGetDateType eGroupType)
        {

            IQueryable<IGrouping<int, DrugDetailUnion>> groupData = null;
            switch (eGroupType)
            {
                case eGroupGetDateType.Month:
                    groupData = drugDetailUnion.GroupBy(d => d.MonitorTime.Month);
                    break;
                case eGroupGetDateType.Quarter:
                    groupData = drugDetailUnion.GroupBy(d => d.Quarter);
                    break;
                case eGroupGetDateType.Year:
                    groupData = drugDetailUnion.GroupBy(d => d.MonitorTime.Year);
                    break;
                default:
                    break;
            }
            return await groupData.
                Select(d => new
                { key = d.Key, Avg = d.Average(dt => dt.ReducedTotal) }).
            ToDictionaryAsync(d => d.key, d => d.Avg);
        }

        public async Task<List<DrugDetailEntity>> GroupByDrugDetailAverage(IQueryable<DrugDetailUnion> drugDetailUnion, eGroupGetDateType eGroupType)
        {
            IQueryable<IGrouping<int, DrugDetailUnion>> groupData = null;

            switch (eGroupType)
            {
                case eGroupGetDateType.Month:
                    groupData = drugDetailUnion.GroupBy(d => d.MonitorTime.Month);
                    break;
                case eGroupGetDateType.Quarter:
                    groupData = drugDetailUnion.GroupBy(d => d.Quarter);
                    break;
                case eGroupGetDateType.Year:
                    groupData = drugDetailUnion.GroupBy(d => d.MonitorTime.Year);
                    break;
                default:
                    break;
            }
            return await groupData.Select(d => new DrugDetailEntity()
            {
                Cyclohexanone = d.Average(x => x.Cyclohexanone),
                Diamorphine = d.Average(x => x.Diamorphine),
                Methylamphetamine = d.Average(x => x.Methylamphetamine),
                Ketamine = d.Average(x => x.Ketamine),
                Ecstasy = d.Average(x => x.Ecstasy),
                Cocaine = d.Average(x => x.Cocaine),
                ID = d.Key
            }).ToListAsync();
        }
        public async Task<List<DrugDetailEntity>> GroupByDrugDetailPlaceAverageAsync(IQueryable<DrugDetailUnion> drugDetailUnion)
        {

            return await drugDetailUnion.GroupBy(d => d.MonitoringSite).Select(d => new DrugDetailEntity()
            {
                Cyclohexanone = d.Average(x => x.Cyclohexanone),
                Diamorphine = d.Average(x => x.Diamorphine),
                Methylamphetamine = d.Average(x => x.Methylamphetamine),
                Ketamine = d.Average(x => x.Ketamine),
                Ecstasy = d.Average(x => x.Ecstasy),
                Cocaine = d.Average(x => x.Cocaine),
                ReducedTotal = d.Average(x => x.ReducedTotal),
                MonitoringSite = d.Key
            }).ToListAsync();
        }

        public  IQueryable<DrugDetailEntity> GroupByDrugDetailPlaceAverage(IQueryable<DrugDetailUnion> drugDetailUnion)
        {

            return drugDetailUnion.GroupBy(d => d.MonitoringSite).Select(d => new DrugDetailEntity()
            {
                Cyclohexanone =Math.Round(d.Average(x => x.Cyclohexanone),2),
                Diamorphine =Math.Round( d.Average(x => x.Diamorphine),2),
                Methylamphetamine = Math.Round(d.Average(x => x.Methylamphetamine),2),
                Ketamine = Math.Round(d.Average(x => x.Ketamine),2),
                Ecstasy = Math.Round(d.Average(x => x.Ecstasy),2),
                Cocaine = Math.Round(d.Average(x => x.Cocaine),2),
                MonitoringSite = d.Key
            });
        }

        public async Task<List<PieView>> GetTimeGroupByQuarterOrMonth(IQueryable<DrugDetailEntity> drugs, int eGroupType)
        {
            IQueryable<IGrouping<int, DrugDetailEntity>> groupdrug = null;
            if (drugs == null)
                return null;
            if (eGroupType == (int)eGroupGetDateType.Quarter)
            {
                groupdrug = drugs.GroupBy(d => d.Quarter);
            }
            else if (eGroupType == (int)eGroupGetDateType.Month)
            {
                groupdrug = drugs.GroupBy(d => d.MonitorTime.Month);
            }

            else if (eGroupType == (int)eGroupGetDateType.Year)
            {
                groupdrug = drugs.GroupBy(d => d.MonitorTime.Year);
            }
            return await groupdrug.Select(d => new PieView() { Name = d.Key.ToString(), Value = d.Key }).ToListAsync();
        }

        public async Task<DateDto> GroupByDate(IQueryable<DrugDetailUnion> drugDetailUnion)
        {

            var groupData = drugDetailUnion.GroupBy(d => new {d.MonitorTime.Year,d.MonitorTime.Month,d.Quarter });

            return await groupData.OrderByDescending(c =>c.Key.Year).
                ThenByDescending(c=>c.Key.Month).Select(d => new DateDto()
            {
                Month = d.Key.Month,
                Quarter = d.Key.Quarter,
                Year = d.Key.Year
            }).Take(1).Skip(0).FirstOrDefaultAsync();
        }


        public async Task<List<DrugDetailReprot>> GroupDrugDetails(IQueryable<DrugDetailUnion> drugDetails)
        {

            if (systemConfig.QuarterOrMonth == (int)eGroupGetDateType.Month)
            {
                return await drugDetails.GroupBy(t => new { t.CityName, t.AreaName, t.MonitoringSite, t.AreaID, t.CompanyID, t.MonitorTime.Month, t.MonitorTime.Year }).Select(d => new DrugDetailReprot
                {
                    Cyclohexanone = d.Average(x => x.Cyclohexanone),
                    Diamorphine = d.Average(x => x.Diamorphine),
                    Methylamphetamine = d.Average(x => x.Methylamphetamine),
                    Ketamine = d.Average(x => x.Ketamine),
                    Ecstasy = d.Average(x => x.Ecstasy),
                    Cocaine = d.Average(x => x.Cocaine),
                    ReducedTotal = d.Average(x => x.ReducedTotal),
                    AreaID = d.Key.AreaID,
                    AreaName = d.Key.AreaName,
                    CityName = d.Key.CityName,
                    MonitoringSite = d.Key.MonitoringSite,
                    Quarter = d.Key.Month,
                    CompanyID = d.Key.CompanyID,
                    Year = d.Key.Year,

                }).OrderByDescending(t => t.ReducedTotal).ToListAsync();
            }

            if (systemConfig.QuarterOrMonth == (int)eGroupGetDateType.Quarter)
            {
                return await drugDetails.GroupBy(t => new { t.CityName, t.AreaName, t.MonitoringSite, t.AreaID, t.CompanyID, t.Quarter, t.MonitorTime.Year }).Select(d => new DrugDetailReprot
                {
                    Cyclohexanone = d.Average(x => x.Cyclohexanone),
                    Diamorphine = d.Average(x => x.Diamorphine),
                    Methylamphetamine = d.Average(x => x.Methylamphetamine),
                    Ketamine = d.Average(x => x.Ketamine),
                    Ecstasy = d.Average(x => x.Ecstasy),
                    Cocaine = d.Average(x => x.Cocaine),
                    ReducedTotal = d.Average(x => x.ReducedTotal),
                    AreaID = d.Key.AreaID,
                    AreaName = d.Key.AreaName,
                    CityName = d.Key.CityName,
                    MonitoringSite = d.Key.MonitoringSite,
                    Quarter = d.Key.Quarter,
                    CompanyID = d.Key.CompanyID,
                    Year = d.Key.Year,

                }).OrderByDescending(t => t.ReducedTotal).ToListAsync();
            }

            return null;

        }

    }
}
